/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation. David Corbin -
 * Original implementation in PendingChangelistView.
 ******************************************************************************/
package net.sourceforge.perforce.ui.action;

import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.api.IWhereResult;
import net.sourceforge.perforce.core.internal.P4TeamProvider;
import net.sourceforge.perforce.core.resources.IP4File;
import net.sourceforge.perforce.ui.PerforceUIPlugin;
import net.sourceforge.perforce.ui.internal.Policy;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 * @author <a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
 */
public class RevertFromChangelistAction extends PerforceAction {
  //----------------------------------------------------------------------------
  // -- Public Methods

  @Override
  public void run(IAction action) {
    if (!shouldContinue()) {
      return;
    }

    run(new IRunnableWithProgress() {
      @SuppressWarnings("unused")
      // InvocationTargetException, InterruptedException
      public void run(IProgressMonitor monitor) throws InvocationTargetException,
          InterruptedException {
        IP4File[] files = getSelectedP4Files();

        MultiStatus status =
            new MultiStatus(PerforceUIPlugin.ID, IStatus.ERROR, Policy
                .bind("RevertFromChangelistAction.errorStatusMessage"), //$NON-NLS-1$
                null);

        ArrayList<String> filenameList = new ArrayList<String>();
        monitor.beginTask("", files.length * 200);
        monitor.setTaskName(Policy.bind("RevertFromChangelistAction.revertingTask")); //$NON-NLS-1$
        for (int i = 0; i < files.length && !monitor.isCanceled(); i++) {
          try {
            IP4File file = files[i];
            IPerforceServer server = file.getServer();

            IWhereResult whereResult = server.where(file.getDepotFilename());
            filenameList.add(whereResult.getLocalFilename());
            monitor.subTask(Policy.bind("RevertFromChangelistAction.revertingSubTask", //$NON-NLS-1$
                whereResult.getLocalFilename()));

            IProgressMonitor subMonitor = Policy.subMonitorFor(monitor, 100);
            server.revert(new String[] {file.getDepotFilename()}, subMonitor);
          } catch (PerforceException e) {
            status.merge(e.getStatus());
          }
        }

        IWorkspaceRoot root = PerforceUIPlugin.getWorkspace().getRoot();
        for (Iterator<String> it = filenameList.iterator(); it.hasNext();) {
          String filename = it.next();

          IFile[] workspaceFiles = root.findFilesForLocation(new Path(filename));
          for (int i = 0; i < workspaceFiles.length; i++) {
            final IFile file = workspaceFiles[i];
            P4TeamProvider provider = P4TeamProvider.getProvider(file);

            IProgressMonitor subMonitor = Policy.subMonitorFor(monitor, 100);
            provider.refreshState(new IResource[] {file}, IResource.DEPTH_ZERO, subMonitor);
          }
        }

        monitor.done();

        if (!status.isOK()) {
          displayErrorDialog(status);
        }
      }
    }, PROGRESS_DIALOG);
  }

  // ---------------------------------------------------------------------------
  // Protected Methods

  @SuppressWarnings("unused")
  // PerforceException
  @Override
  protected boolean isEnabled() throws PerforceException {
    return true;
  }

  //----------------------------------------------------------------------------
  // - Private Methods

  /**
   * Called to ask the user for confirmation.
   * 
   * @return true if we should continue, false otherwise.
   */
  private boolean shouldContinue() {
    boolean shouldContinue =
        MessageDialog.openConfirm(getShell(), Policy.bind("RevertAction.confirmDialogTitle"), //$NON-NLS-1$
            Policy.bind("RevertAction.confirmDialogMessage")); //$NON-NLS-1$
    return shouldContinue;
  }

  /**
   * Called to display an error dialog for the given status.
   * 
   * @param status the status
   */
  private void displayErrorDialog(final IStatus status) {
    Display display = getShell().getDisplay();
    display.asyncExec(new Runnable() {
      public void run() {
        ErrorDialog.openError(getShell(), Policy.bind("simpleInternal"), //$NON-NLS-1$
            Policy.bind("RevertFromChangelistAction.errorMessage"), //$NON-NLS-1$
            status);
      }
    });
  }

}
